package me.thinkjet.sso.client.filter;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import me.thinkjet.sso.client.util.CommonUtils;
import me.thinkjet.sso.client.util.HttpUtils;
import me.thinkjet.sso.client.validation.Assertion;
import me.thinkjet.sso.client.validation.TicketValidationException;
import me.thinkjet.sso.client.validation.TicketValidator;

public abstract class AbstractTicketValidationFilter extends AbstractFilter {

	private TicketValidator ticketValidator;

	private boolean redirectAfterValidation = true;

	protected TicketValidator getTicketValidator(final FilterConfig filterConfig) {
		return this.ticketValidator;
	}

	protected void initInternal(final FilterConfig filterConfig)
			throws ServletException {
		setRedirectAfterValidation(parseBoolean(getPropertyFromInitParams(
				filterConfig, "redirectAfterValidation", "true")));
		setTicketValidator(getTicketValidator(filterConfig));
		super.initInternal(filterConfig);
	}

	public void init() {
		super.init();
		CommonUtils.assertNotNull(this.ticketValidator,
				"ticketValidator cannot be null.");
	}

	protected void onSuccessfulValidation(final HttpServletRequest request,
			final HttpServletResponse response, final Assertion assertion) {
	}

	protected void onFailedValidation(final HttpServletRequest request,
			final HttpServletResponse response) {
	}

	public final void doFilter(final ServletRequest servletRequest,
			final ServletResponse servletResponse, final FilterChain filterChain)
			throws IOException, ServletException {

		final HttpServletRequest request = (HttpServletRequest) servletRequest;
		final HttpServletResponse response = (HttpServletResponse) servletResponse;
		final String ticket = HttpUtils.safeGetParameter(request,
				getTicketName());

		if (CommonUtils.isNotBlank(ticket)) {
			try {
				final Assertion assertion = this.ticketValidator
						.validate(ticket);

				request.setAttribute(CONST_SSO_ASSERTION, assertion);

				request.getSession().setAttribute(CONST_SSO_ASSERTION,
						assertion);
				onSuccessfulValidation(request, response, assertion);

				if (this.redirectAfterValidation) {
					response.sendRedirect(constructServiceUrl(request, response));
					return;
				}
			} catch (final TicketValidationException e) {
				response.setStatus(HttpServletResponse.SC_FORBIDDEN);
				onFailedValidation(request, response);

				return;
			}
		}

		filterChain.doFilter(request, response);

	}

	public final void setTicketValidator(final TicketValidator ticketValidator) {
		this.ticketValidator = ticketValidator;
	}

	public final void setRedirectAfterValidation(
			final boolean redirectAfterValidation) {
		this.redirectAfterValidation = redirectAfterValidation;
	}

}
